<?php
namespace App\Common\Cla\EChat\Server\ReceivePools;

use App\Common as com;
use App\Common\Cla\EChat\Server\ReceivePools\Item as thisItem;
use App\Common\Cla\EChat as nameEChat;

class Item extends com\Cla\ClaBase {

	/**
	 * 接收id
	 * @var int
	 */
	private int $receiveId;

	/**
	 * 频道名
	 * @var string
	 */
	private string $channelSid;

	/**
	 * 房间sid
	 * @var string
	 */
	private string $roomSid;

	/**
	 * 接收回调
	 * @var \Closure
	 */
	private \Closure $msgCallback;

	/**
	 * 接收接收回调
	 * @var \Closure
	 */
	private \Closure $stopCallback;

	/**
	 * 接收超时
	 * @var int|null
	 */
	private ?int $receiveTimeoutS;

	/**
	 * 最后接收时间
	 * @var int|null
	 */
	private ?int $lastReceiveTime = null;

	/**
	 * 接收超时定时器id
	 * @var int|null
	 */
	private ?int $receiveTimeTimerId = null;

	/**
	 * 等待通道
	 * @var \Swoole\Coroutine\Channel
	 */
	private \Swoole\Coroutine\Channel $waitChannel;

	/**
	 * Item constructor.
	 * @param int $receiveId
	 * @param string $channelSid
	 * @param string $roomSid
	 * @param \Closure $msgCallback
	 * @param \Closure $stopCallback
	 * @param int $receiveTimeoutS 接收超时（单位：秒） [null]不超时
	 */
	public function __construct( int $receiveId, string $channelSid, string $roomSid, \Closure $msgCallback, \Closure $stopCallback, ?int $receiveTimeoutS = null ) {
		$this->receiveId = $receiveId;
		$this->channelSid = $channelSid;
		$this->roomSid = $roomSid;
		$this->msgCallback = $msgCallback;
		$this->stopCallback = $stopCallback;
		$this->receiveTimeoutS = $receiveTimeoutS;
		//
		$this->restartCheckReceiveTimeoutTimer();
		//
		parent::__construct();
	}

	public function __destruct(  ) {
		// 删除定时器
		$this->clearCheckReceiveTimeoutTimer();
	}

	/**
	 * 开启接收超时定时
	 * @return $this
	 */
	private function restartCheckReceiveTimeoutTimer():self {
		$this->clearCheckReceiveTimeoutTimer();
		//
		if( $this->receiveTimeoutS > 0 ){
			$this->receiveTimeTimerId = \Swoole\Timer::after( $this->getReceiveTimeoutS() * 1000, function(){
				$this->stopReceive();
			} );
		}
		//
		return $this;
	}

	/**
	 * 删除接收超时定时
	 * @return $this
	 */
	private function clearCheckReceiveTimeoutTimer():self {
		if( $this->receiveTimeTimerId > 0 ){
			\Swoole\Timer::clear( $this->receiveTimeTimerId );
		}
		//
		return $this;
	}

	public function getReceiveId(  ):int {
		return $this->receiveId;
	}

	public function getChannelSid(  ):string {
		return $this->channelSid;
	}

	public function getRoomSid(  ):string {
		return $this->roomSid;
	}

	/**
	 * @return \Closure
	 */
	public function getMsgCallback(  ):\Closure {
		return $this->msgCallback;
	}

	/**
	 * @return \Closure
	 */
	public function getStopCallback(  ):\Closure {
		return $this->stopCallback;
	}

	/**
	 * @return int
	 */
	public function getReceiveTimeoutS(  ):int {
		return $this->receiveTimeoutS;
	}

	/**
	 * 调用
	 * @param \PhpAmqpLib\Message\AMQPMessage $AMQPMsg
	 * @return bool
	 */
	public function callReceive( \PhpAmqpLib\Message\AMQPMessage $AMQPMsg ):bool {
		$this->restartCheckReceiveTimeoutTimer();
		//
		call_user_func( $this->getMsgCallback(), $AMQPMsg, $this );
		//
		return true;
	}

	/**
	 * 调用结束接收回调
	 * @return bool
	 */
	public function callStopCallback():bool {
		call_user_func( $this->getStopCallback(), $this );
		//
		return true;
	}

	/**
	 * 等待
	 * @param int|null $waitTimeoutS 等待超时时间。单位：秒
	 * @return bool 是否已结束 [true]正常结束 [fasle]超时或已关闭
	 */
	public function waitReceive( ?int $waitTimeoutS = null ):bool {
		if( ! isset( $this->waitChannel ) ){
			$this->waitChannel = new \Swoole\Coroutine\Channel();
		}
		//
		return $this->waitChannel->pop( $waitTimeoutS );
	}


	/**
	 * @return bool
	 */
	public function stopReceive():bool {
		// 发送关闭信号
		if( isset( $this->waitChannel ) ){
			$this->waitChannel->push( true );
		}
		//
		return nameEChat\Server::makeOfStatic()->stopReceive( $this->getReceiveId() );
	}

	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	/**
	 * @param int $receiveId
	 * @param string $channelSid
	 * @param string $roomSid
	 * @param \Closure $msgCallback
	 * @param \Closure $stopCallback
	 * @param int|null $receiveTimeoutS 接收超时（单位：秒） [null]不超时
	 * @return $this
	 */
	public static function makeOfNew( int $receiveId, string $channelSid, string $roomSid, \Closure $msgCallback, \Closure $stopCallback, ?int $receiveTimeoutS = null ):self {
	    return self::make( $receiveId, $channelSid, $roomSid, $msgCallback, $stopCallback, $receiveTimeoutS );
	}

}
